package datastructure.tree;

import java.util.Comparator;

/**
 * @Description:
 * @Author Ammar
 * @Create 2023/3/27 12:46
 */
public class BinarySearchTree<E> extends BinaryTree<E> {
    private Comparator<E> comparetor;

    public BinarySearchTree() {
        this(null);
    }

    public <E> BinarySearchTree(Comparator<E> comparator) {
    }

    // 添加元素
    @Override
    public void add(E val) {
        elementNotNullCheck(val);
        // 添加第一个节点
        if (root == null) {
            root = createNode(val, null);
            size++;
            afterAdd(root);
            return;
        }

        // 添加的不是第一个节点
        TreeNode<E> node = root;
        TreeNode<E> parent = root;
        int compare = 0;
        while (node != null) {
            compare = compareTo(val, node.val);
            parent = node;
            // 如果添加元素大于比较元素，放右边，否则放左边
            if (compare > 0) {
                node = node.right;
            } else if (compare < 0) {
                node = node.left;
            } else {
                node.val = val;
                return;
            }
        }
        // 保存到父节点的左边还是右边
        TreeNode<E> newNode = createNode(val, parent);
        if (compare > 0) {
            parent.right = newNode;
        } else {
            parent.left = newNode;
        }
        size++;
        // 新添加节点之后的处理
        afterAdd(newNode);
    }

    // 删除元素
    public void remove(E element) {
        remove(node(element));
    }
    private void remove(TreeNode node) {
        if (node == null) return;
        size--;
        // 度为2的节点
        if (node.hasTwoChildren()) {
            // 找到后继节点
            TreeNode<E> s = successor(node);
            // 用后继节点的值覆盖度为2的节点的值
            node.val = s.val;
            // 删除后继节点，
            node = s;
        }
        // 删除node节点(node的度必然是1或者0)
        TreeNode<E> replacement = node.left != null ? node.left : node.right;
        if (replacement != null) {
            // node是度为1的节点
            // 将要接替node节点的节点replacement的parent指向node的parent
            // 此时，如果再将 node.parent的left或者right指向replacement，就完成了删除node节点的操作
            replacement.parent = node.parent;
            // 更改parent的left、right的指向
            if (node.parent == null) {
                // node是度为1的节点并且是根节点
                root = replacement;
            } else if (node == node.parent.left) {
                node.parent.left = replacement;
            } else {
                node.parent.right = replacement;
            }
            // 删除节点之后的调整
            afterRemove(node, replacement);
        }
        // replacement == null 且 node.parent == null，说明node是叶子节点并且是根节点
        else if (node.parent == null) {
            root = null;
            // 删除节点之后的调整
            afterRemove(node, null);
        } else {
            // node是叶子节点，但不是根节点
            if (node == node.parent.left) {
                node.parent.left = null;
            } else {
                node.parent.right = null;
            }
            // 删除节点之后的调整
            afterRemove(node, null);
        }
    }

    // 删除节点之后的调整
    protected void afterRemove(TreeNode<E> node, TreeNode<E> replacement) {
    }

    // 获取元素对应的节点
    private TreeNode<E> node(E element) {
        TreeNode<E> node = root;
        while (node != null) {
            int compare = compareTo(element, node.val);
            if (compare == 0) return node;
            if (compare > 0) {
                node = node.right;
            } else {
                node = node.left;
            }
        }
        return null;
    }
    // 是否包含某元素
    public boolean contains(E element) {
        return node(element) != null;
    }
    private int compareTo(E e1, E e2) {
        if (comparetor != null) {
            return comparetor.compare(e1, e2);
        }
        return ((Comparable<E>) e1).compareTo(e2);
    }
}
